package hn.cch.http.server;

import hn.cch.aspect.HttpAop;
import hn.cch.bean.Bean;
import io.netty.channel.ChannelFutureListener;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.handler.codec.http.*;
import io.netty.util.AsciiString;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import java.util.List;
import java.util.Map;

/**
 * HTTP事件处理
 */

@Component
public class HttpHandler extends ChannelInboundHandlerAdapter {

    private static Logger logger = LoggerFactory.getLogger(HttpHandler.class);


    private boolean keepAlive = false;
    private int contentLength = 0;

    //    private ByteBuf byteBuf = null;
    private String string = null;
    private byte[] bytes = null;

//    private HttpReqMsg httpReqMsg = new HttpReqMsg();
//    private HttpRespMsg httpRespMsg = new HttpRespMsg();


    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {

        logger.info("http message class : " + msg.getClass());

        if (msg instanceof HttpRequest) {
            logger.info("http message class : HttpRequest");
            HttpRequest httpRequest = (HttpRequest) msg;


            keepAlive = HttpUtil.isKeepAlive(httpRequest);
            logger.info("http keep alive : " + keepAlive);

            contentLength = (int) HttpUtil.getContentLength(httpRequest);
            logger.info("http content length : " + contentLength);
            //byteBuf = ctx.alloc().buffer(contentLength);
            bytes = new byte[contentLength];
            string = httpRequest.uri();


            logger.info("http get uri param");
            String uri = httpRequest.uri();
            logger.info("http get uri : " + uri);

            QueryStringDecoder queryStringDecoder = new QueryStringDecoder(uri);
            String path = queryStringDecoder.path();
            //httpReqMsg.getGet().setPath(path);
            logger.info("http get path : " + path);

            logger.info("http get param : ");
            Map<String, List<String>> params = queryStringDecoder.parameters();
            if (!params.isEmpty()) {
                for (Map.Entry<String, List<String>> param : params.entrySet()) {
                    String key = param.getKey();
                    List<String> values = param.getValue();
                    for (String value : values) {
                        //httpReqMsg.getGet().getParams().put(key, value);
                        logger.info("    " + key + "=" + value);
                    }
                }
            }

            logger.info("http message header : ");
            HttpHeaders httpHeaders = httpRequest.headers();
            if (!httpHeaders.isEmpty()) {
                for (Map.Entry<String, String> httpHeader : httpHeaders) {
                    CharSequence key = httpHeader.getKey();
                    CharSequence value = httpHeader.getValue();
                    logger.info("    " + key + "=" + value);
                }
            }


//            HttpMethod httpMethod = httpRequest.method();
//            logger.info("http message method : " + httpMethod.name());
//            if (httpMethod.equals(HttpMethod.GET)){
//
//
//            }
//            if (httpMethod.equals(HttpMethod.POST)){
//
//            }








        }

        if (msg instanceof HttpContent) {
            logger.info("http message class : HttpContent");

            HttpContent httpContent = (HttpContent) msg;
//            httpContent.content().readBytes(byteBuf);
            httpContent.content().readBytes(bytes);


            if (msg instanceof LastHttpContent) {
                logger.info("http message class : LastHttpContent");

//                byteBuf.readBytes(bytes);

                /*
                URI的格式固定：/http/api/test?type=main&user=XXXX&hash=XXXXXXXXXXXXXXXXX
                path=/http/api/test
                type=test
                user=XXXX
                hash=XXXXXXXXXXXXXXXXX
                 */

                HttpAop httpAop = (HttpAop) Bean.getBean("httpAop");
                byte[] content = httpAop.aop(string, bytes);




//                ParamClass param = (ParamClass)JsonUtil.toObject(Des3Util.crypt(2, bytes, Des3Util.key), TestParam.class);
//
//                httpReqMsg.getPost().setParam(param);
//
//                HttpApi httpApi = (HttpApi) Bean.getBean(httpReqMsg.getGet().getPath());
//
//                httpRespMsg =
//
//                return Des3Util.crypt(1, JsonUtil.toBytes(httpRespMsg), Des3Util.key);





//                HttpApi httpApi = (HttpApi) Bean.getBean(httpReqMsg.getGet().getPath());
//                byte[] content = (byte[]) httpApi.post(bytes);


                DefaultFullHttpResponse defaultFullHttpResponse = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.OK);

                defaultFullHttpResponse.content().writeBytes(content);

                defaultFullHttpResponse.headers().set(HttpHeaderNames.CONTENT_TYPE, "text/plain");
                defaultFullHttpResponse.headers().set(HttpHeaderNames.CONTENT_LENGTH, content.length);

                if (keepAlive) {
                    defaultFullHttpResponse.headers().set(HttpHeaderNames.CONNECTION, new AsciiString("keep-alive"));
                    ctx.write(defaultFullHttpResponse);
                } else {
                    ctx.write(defaultFullHttpResponse).addListener(ChannelFutureListener.CLOSE);
                }


            }
        }
    }

    @Override
    public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
        logger.info("channelReadComplete");
        ctx.flush();
        logger.info("ctx.flush");
        ctx.close();
        logger.info("ctx.close");
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        logger.error("exceptionCaught");
        cause.printStackTrace();
    }
}

